home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1989, 1992, 1993, 1994 Aladdin Enterprises. All rights reserved.
-
- This file is part of Aladdin Ghostscript.
-
- Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
- or distributor accepts any responsibility for the consequences of using it,
- or for whether it serves any particular purpose or works at all, unless he
- or she says so in writing. Refer to the Aladdin Ghostscript Free Public
- License (the "License") for full details.
-
- Every copy of Aladdin Ghostscript must include a copy of the License,
- normally in a plain ASCII text file named PUBLIC. The License grants you
- the right to copy, modify and redistribute Aladdin Ghostscript, but only
- under certain conditions described in the License. Among other things, the
- License requires that the copyright notice and this notice be preserved on
- all copies.
- */
-
- /* gp_amiga.c */
- /* Amiga-specific routines for Ghostscript */
- #include <dos/dosextens.h>
- #include <graphics/gfxbase.h>
- #include <intuition/intuitionbase.h>
-
- #include <proto/dos.h>
- #include <proto/exec.h>
- #include <proto/intuition.h>
-
- #include <sys/types.h>
- #undef _POSIX_SOURCE
- #include <sys/dirent.h>
- typedef struct dirent dir_entry;
- #include "stat_.h"
- #include "string_.h"
- #include "time_.h"
- #include "gx.h"
- #include "gp.h"
- #include "gsexit.h"
- #include "gsstruct.h"
- #include "gsutil.h"
-
- #include <signal.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/param.h> /* for MAXPATHLEN */
-
- #if defined(mc68020)
- #ifdef __HAVE_68881__
- STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" GSDATE ") MC68020/FPU version\r\n";
- #else
- STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" GSDATE ") MC68020 version\r\n";
- #endif /* __HAVE_68881__ */
- #elif defined(mc68030)
- #ifdef __HAVE_68881__
- STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" GSDATE ") MC68030/FPU version\r\n";
- #else
- STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" GSDATE ") MC68030 version\r\n";
- #endif /* __HAVE_68881__ */
- #elif defined(mc68040)
- #ifdef __HAVE_68881__
- STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" GSDATE ") MC68040/FPU version\r\n";
- #else
- STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" GSDATE ") MC68040 version\r\n";
- #endif /* __HAVE_68881__ */
- #elif defined(mc68060)
- #ifdef __HAVE_68881__
- STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" GSDATE ") MC68060/FPU version\r\n";
- #else
- STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" GSDATE ") MC68060 version\r\n";
- #endif /* __HAVE_68881__ */
- #else
- STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" __DATE2__ ")\r\n";
- #endif /* mc68020 */
-
- /*struct IntuitionBase *IntuitionBase;
- struct GfxBase *GfxBase;
- struct Library *LayersBase,
- *IFFParseBase,
- *AslBase,
- *UtilityBase;*/
- /*struct DosLibrary *DOSBase;
- struct MathIEEEBase *MathIeeeDoubBasBase;*/
-
- /* Cleanup routine, as called by atexit() trap */
- void
- cleanup(void)
- {
- extern void devcleanup(void);
-
- // devcleanup();
-
- /* if(IFFParseBase)
- {
- CloseLibrary(IFFParseBase);
-
- IFFParseBase = NULL;
- }
-
- if(AslBase)
- {
- CloseLibrary(AslBase);
-
- AslBase = NULL;
- }
-
- if(UtilityBase)
- {
- CloseLibrary(UtilityBase);
-
- UtilityBase = NULL;
- }
-
- if(LayersBase)
- {
- CloseLibrary(LayersBase);
-
- LayersBase = NULL;
- }
-
- if(GfxBase)
- {
- CloseLibrary((struct Library *)GfxBase);
-
- GfxBase = NULL;
- }
-
- if(IntuitionBase)
- {
- CloseLibrary((struct Library *)IntuitionBase);
-
- IntuitionBase = NULL;
- }*/
- }
-
- /*void
- signal_handler(int signal)
- {
- fprintf(stderr,"*** BREAK: Ghostscript\a\n");
-
- gs_exit(1);
- }*/
-
- /* Do platform-dependent initialization. */
- void
- gp_init(void)
- {
- atexit(cleanup);
-
- // signal(SIGINT,signal_handler);
-
- /* if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)))
- {
- eprintf("Ghostscript: cannot open intuition.library v37\n");
-
- exit(20);
- }
-
- if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37)))
- {
- eprintf("Ghostscript: cannot open graphics.library v37\n");
-
- exit(20);
- }
-
- if(!(LayersBase = OpenLibrary("layers.library",37)))
- {
- eprintf("Ghostscript: cannot open layers.library v37\n");
-
- exit(20);
- }
-
- if(!(UtilityBase = OpenLibrary("utility.library",37)))
- {
- eprintf("Ghostscript: cannot open utility.library v37\n");
-
- exit(20);
- }*/
-
- /* if(!(IFFParseBase = OpenLibrary("iffparse.library",37)))
- {
- eprintf("Ghostscript: cannot open iffparse.library v37\n");
-
- exit(20);
- }*/
-
- // AslBase = OpenLibrary("asl.library",38);
- }
-
- /* Do platform-dependent cleanup. */
- void
- gp_exit(int exit_status, int code)
- {
- cleanup();
- }
-
- /* Exit the program. */
- void
- gp_do_exit(int exit_status)
- { exit(exit_status);
- }
-
- /* ------ Miscellaneous ------ */
-
- /*
- * Get the string corresponding to an OS error number.
- * If no string is available, return NULL. The caller may assume
- * the string is allocated statically and permanently.
- */
- const char *
- gp_strerror(int errnum)
- { return (strerror(errnum));
- }
-
- /* ------ Date and time ------ */
-
- /* Read the current time (in seconds since Jan. 1, 1970) */
- /* and fraction (in nanoseconds). */
- void
- gp_get_realtime(long *pdt)
- {
- #if defined(IXEMUL)
- struct timeval tp;
-
- #if gettimeofday_no_timezone /* older versions of SVR4 */
- { if ( gettimeofday(&tp) == -1 )
- { lprintf("Ghostscript: gettimeofday failed!\n");
- gs_exit(1);
- }
- }
- #else /* All other systems */
- { struct timezone tzp;
- if ( gettimeofday(&tp, &tzp) == -1 )
- { lprintf("Ghostscript: gettimeofday failed!\n");
- gs_exit(1);
- }
- }
- #endif
- /* tp.tv_sec is #secs since Jan 1, 1970 */
- pdt[0] = tp.tv_sec;
-
- /* Some Unix systems (e.g., Interactive 3.2 r3.0) return garbage */
- /* in tp.tv_usec. Try to filter out the worst of it here. */
- pdt[1] = tp.tv_usec >= 0 && tp.tv_usec < 1000000 ? tp.tv_usec*1000 : 0;
-
- #else
- LONG secs, micros;
-
- CurrentTime(&secs, µs);
-
- pdt[0] = secs;
- pdt[1] = micros*1000;
-
- #endif
- #ifdef DEBUG_CLOCK
- printf("tp.tv_sec = %d tp.tv_usec = %d pdt[0] = %ld pdt[1] = %ld\n",
- tp.tv_sec, tp.tv_usec, pdt[0], pdt[1]);
- #endif
- }
-
- /* Read the current user CPU time (in seconds) */
- /* and fraction (in nanoseconds). */
- void
- gp_get_usertime(long *pdt)
- {
- #if use_times_for_usertime
- LONG secs, micros;
-
- CurrentTime(&secs, µs);
-
- pdt[0] = secs;
- pdt[1] = micros*1000;
- #else
- gp_get_realtime(pdt); /* Use an approximation on other hosts. */
- #endif
- }
-
- /* ------ Screen management ------ */
-
- /* Get the environment variable that specifies the display to use. */
- const char *
- gp_getenv_display(void)
- { return getenv("DISPLAY");
- }
-
- /* ------ Printer accessing ------ */
-
- /* Open a connection to a printer. A null file name means use the */
- /* standard printer connected to the machine, if any. */
- /* "|command" opens an output pipe. */
- /* Return NULL if the connection could not be opened. */
- FILE *
- gp_open_printer(char *fname, int binary_mode)
- {
- #ifndef IXEMUL
- return
- (strlen(fname) == 0 ?
- gp_open_scratch_file(gp_scratch_file_name_prefix, fname, "wb+") :
- fname[0] == '|' ?
- NULL :
- fopen(fname, "wb+"));
- #else
- return
- (strlen(fname) == 0 ?
- gp_open_scratch_file(gp_scratch_file_name_prefix, fname, "w") :
- fname[0] == '|' ?
- popen(fname + 1, "w") :
- fopen(fname, "w"));
- #endif
- }
-
- /* Close the connection to the printer. */
- void
- gp_close_printer(FILE *pfile, const char *fname)
- {
- #ifndef IXEMUL
- fclose(pfile);
- #else
- if ( fname[0] == '|' )
- pclose(pfile);
- else
- fclose(pfile);
- #endif
- }
-
- /* ------ File name syntax ------ */
-
- /* Define the character used for separating file names in a list. */
- const char gp_file_name_list_separator = ',';
-
- /* Define the string to be concatenated with the file mode */
- /* for opening files without end-of-line conversion. */
- const char gp_fmode_binary_suffix[] __attribute__ ((aligned (4))) = "";
- /* Define the file modes for binary reading or writing. */
- const char gp_fmode_rb[] __attribute__ ((aligned (4))) = "r";
- const char gp_fmode_wb[] __attribute__ ((aligned (4))) = "wb+";
-
- /* Answer whether a file name contains a directory/device specification, */
- /* i.e. is absolute (not directory- or device-relative). */
- int
- gp_file_name_is_absolute(const char *fname, uint len)
- {
- int i;
-
- for(i = 0 ; i < len ; i++)
- {
- if(fname[i] == ':')
- return(1);
- }
-
- return(0);
- }
-
- /* Answer the string to be used for combining a directory/device prefix */
- /* with a base file name. The file name is known to not be absolute. */
- const char *
- gp_file_name_concat_string(const char *prefix, uint plen, const char *fname, uint len)
- {
- #ifdef IXEMUL
- if(plen > 0 && (prefix[plen - 1] == '/' || prefix[plen - 1] == ':'))
- return("");
- else
- return("/");
- #else
- if(plen > 0)
- if(prefix[plen - 1] == '/' || prefix[plen - 1] == ':')
- return("");
- else
- return("/");
- else
- return("");
- #endif
- }
-
- /* ------ File naming and accessing ------ */
-
- /* Define the default scratch file name prefix. */
- #ifdef IXEMUL
- const char gp_scratch_file_name_prefix[] = "/T/gs_";
- #else
- const char gp_scratch_file_name_prefix[] = "T:gs_";
- #endif
- /* Define the name of the null output file. */
- #ifdef IXEMUL
- const char gp_null_file_name[] = "/dev/null";
- #else
- const char gp_null_file_name[] = "NIL:";
- #endif
-
- /* Define the name that designates the current directory. */
- #ifdef IXEMUL
- const char gp_current_directory_name[] = ".";
- #else
- const char gp_current_directory_name[] __attribute__ ((aligned (4))) = "";
- #endif
-
- /* Create and open a scratch file with a given name prefix. */
- /* Write the actual file name at fname. */
- FILE *
- gp_open_scratch_file(const char *prefix, char *fname, const char *mode)
- {
- #ifndef IXEMUL
- char temp2[100];
- struct Task *thistask;
- LONG secs, micros;
- #endif
-
- strcpy(fname,prefix);
- /* Prevent trailing X's in path from being converted by mktemp. */
- if ( *fname != 0 && fname[strlen(fname) - 1] == 'X' )
- strcat(fname, "-");
- #ifdef IXEMUL
- strcat(fname, "XXXXXX");
- #else
- CurrentTime(&secs, µs);
- sprintf(temp2,"%08lx_%08lx_%08lx",FindTask(NULL), secs, micros);
- /* this looks stupid but a reasonable chance exists that you end up with the
- same time if scratch files are opened fast enough
- */
- Delay(25);
- strcat(fname, temp2);
- #endif
- #ifdef IXEMUL
- mktemp(fname);
- #endif
- return fopen(fname, mode);
- }
-
- /* Open a file with the given name, as a stream of uninterpreted bytes. */
- FILE *
- gp_fopen(const char *fname, const char *mode)
- { return fopen(fname, mode);
- }
-
- /* ------ File enumeration ------ */
-
- /* Thanks to Fritz Elfert (Fritz_Elfert@wue.maus.de) for */
- /* the original version of the following code, and Richard Mlynarik */
- /* (mly@adoc.xerox.com) for an improved version. */
-
- typedef struct dirstack_s dirstack;
- struct dirstack_s {
- dirstack *next;
- struct DIR *entry;
- };
- gs_private_st_ptrs1(st_dirstack, dirstack, "dirstack",
- dirstack_enum_ptrs, dirstack_reloc_ptrs, next);
-
- struct file_enum_s
- {
- struct DIR *dirp; /* pointer to current open directory */
- char *pattern; /* original pattern */
- char *work; /* current path */
- int worklen; /* strlen (work) */
- dirstack *dstack; /* directory stack */
- int patlen;
- int pathead; /* how much of pattern to consider
- * when listing files in current directory */
- bool first_time;
- gs_memory_t *memory;
- };
- gs_private_st_ptrs3(st_file_enum, struct file_enum_s, "file_enum",
- file_enum_enum_ptrs, file_enum_reloc_ptrs, pattern, work, dstack);
-
- /* Private procedures */
-
- /* Do a wild-card match. */
- #ifdef DEBUG
- private bool
- wmatch(const byte *str, uint len, const byte *pstr, uint plen,
- const string_match_params *psmp)
- { bool match = string_match(str, len, pstr, plen, psmp);
- if ( gs_debug_c('e') )
- { dputs("[e]string_match(\"");
- fwrite(str, 1, len, dstderr);
- dputs("\", \"");
- fwrite(pstr, 1, plen, dstderr);
- dprintf1("\") = %s\n", (match ? "TRUE" : "false"));
- }
- return match;
- }
- #define string_match wmatch
- #endif
-
- /* Search a string backward for a character. */
- /* (This substitutes for strrchr, which some systems don't provide.) */
- private char *
- rchr(char *str, char ch, int len)
- { register char *p = str + len;
- while ( p > str )
- if ( *--p == ch ) return p;
- return 0;
- }
-
- /* Pop a directory from the enumeration stack. */
- private bool
- popdir(file_enum *pfen)
- { dirstack *d = pfen->dstack;
- if ( d == 0 )
- return false;
- pfen->dirp = d->entry;
- pfen->dstack = d->next;
- gs_free_object(pfen->memory, d, "gp_enumerate_files(popdir)");
- return true;
- }
-
- /* Initialize an enumeration. */
- file_enum *
- gp_enumerate_files_init(const char *pat, uint patlen, gs_memory_t *mem)
- { file_enum *pfen;
- char *p;
- char *work;
-
- /* Reject attempts to enumerate paths longer than the */
- /* system-dependent limit. */
- if ( patlen > MAXPATHLEN )
- return 0;
-
- /* Reject attempts to enumerate with a pattern containing zeroes. */
- { const char *p1;
- for (p1 = pat; p1 < pat + patlen; p1++)
- if (*p1 == 0) return 0;
- }
- /* >>> Should crunch strings of repeated "/"'s in pat to a single "/"
- * >>> to match stupid unix filesystem "conventions" */
-
- pfen = gs_alloc_struct(mem, file_enum, &st_file_enum,
- "gp_enumerate_files");
- if (pfen == 0)
- return 0;
-
- /* pattern and work could be allocated as strings, */
- /* but it's simpler for GC and freeing to allocate them as bytes. */
-
- pfen->pattern =
- (char *)gs_alloc_bytes(mem, patlen + 1,
- "gp_enumerate_files(pattern)");
- if (pfen->pattern == 0)
- return 0;
- memcpy(pfen->pattern, pat, patlen);
- pfen->pattern[patlen] = 0;
-
- work = (char *)gs_alloc_bytes(mem, MAXPATHLEN+1,
- "gp_enumerate_files(work)");
- if (work == 0)
- return 0;
- pfen->work = work;
-
- p = work;
- memcpy(p, pat, patlen);
- p += patlen;
- *p = 0;
-
- /* Remove directory specifications beyond the first wild card. */
- /* Some systems don't have strpbrk, so we code it open. */
- p = pfen->work;
- while ( !(*p == '*' || *p == '?' || *p == 0) ) p++;
- while ( !(*p == '/' || *p == 0) ) p++;
- if ( *p == '/' )
- *p = 0;
- /* Substring for first wildcard match */
- pfen->pathead = p - work;
-
- /* Select the next higher directory-level. */
- p = rchr(work, '/', p - work);
- if (!p)
- { /* No directory specification */
- work[0] = 0;
- pfen->worklen = 0;
- }
- else
- { if (p == work)
- { /* Root directory -- don't turn "/" into "" */
- p++;
- }
- *p = 0;
- pfen->worklen = p - work;
- }
-
- pfen->memory = mem;
- pfen->dstack = 0;
- pfen->first_time = true;
- pfen->patlen = patlen;
- return pfen;
- }
-
- /* Enumerate the next file. */
- uint
- gp_enumerate_files_next(file_enum *pfen, char *ptr, uint maxlen)
- { dir_entry *de;
- char *work = pfen->work;
- int worklen = pfen->worklen;
- char *pattern = pfen->pattern;
- int pathead = pfen->pathead;
- int len;
- struct stat stbuf;
-
- if ( pfen->first_time )
- { pfen->dirp = ((worklen == 0) ? opendir(".") : opendir(work));
- if_debug1('e', "[e]file_enum:First-Open '%s'\n", work);
- pfen->first_time = false;
- if (pfen->dirp == 0) /* first opendir failed */
- { gp_enumerate_files_close(pfen);
- return ~(uint)0;
- }
- }
-
- top: de = readdir(pfen->dirp);
- if (de == 0)
- { /* No more entries in this directory */
- char *p;
-
- if_debug0('e', "[e]file_enum:Closedir\n");
- closedir(pfen->dirp);
- /* Back working directory and matching pattern up one level */
- p = rchr(work,'/', worklen);
- if (p != 0)
- { if (p == work) p++;
- *p = 0;
- worklen = p - work;
- }
- else
- worklen = 0;
- p = rchr(pattern,'/', pathead);
- if (p != 0)
- pathead = p - pattern;
- else
- pathead = 0;
-
- if (popdir(pfen))
- { /* Back up the directory tree. */
- if_debug1('e', "[e]file_enum:Dir popped '%s'\n", work);
- goto top;
- }
- else
- { if_debug0('e', "[e]file_enum:Dirstack empty\n");
- gp_enumerate_files_close(pfen);
- return ~(uint)0;
- }
- }
-
- /* Skip . and .. */
- len = strlen(de->d_name);
- if (len <= 2 && (!strcmp(de->d_name,".") || !strcmp(de->d_name,"..") ))
- goto top;
- if (len + worklen + 1 > MAXPATHLEN)
- /* Should be an error, I suppose */
- goto top;
- if (worklen == 0)
- { /* "Current" directory (evil un*x kludge) */
- memcpy(work, de->d_name, len + 1);
- }
- else if (worklen == 1 && work[0] == '/')
- { /* Root directory */
- memcpy(work + 1, de->d_name, len + 1);
- len = len + 1;
- }
- else
- { work[worklen] = '/';
- memcpy(work + worklen + 1, de->d_name, len + 1);
- len = worklen + 1 + len;
- }
-
- /* Test for a match at this directory level */
- if (!string_match((byte *)work, len, (byte *)pattern, pathead, NULL))
- goto top;
-
- /* Perhaps descend into subdirectories */
- if (pathead < pfen->patlen)
- { struct DIR *dp;
-
- if (((stat(work,&stbuf) >= 0)
- ? !stat_is_dir(stbuf)
- /* Couldn't stat it.
- * Well, perhaps it's a directory and
- * we'll be able to list it anyway.
- * If it isn't or we can't, no harm done. */
- : 0))
- goto top;
-
- if (pfen->patlen == pathead + 1)
- { /* Listing "foo/?/" -- return this entry */
- /* if it's a directory. */
- if (!stat_is_dir (stbuf))
- { /* Do directoryp test the hard way */
- dp = opendir(work);
- if (!dp) goto top;
- closedir(dp);
- }
- work[len++] = '/';
- goto winner;
- }
-
- /* >>> Should optimise the case in which the next level */
- /* >>> of directory has no wildcards. */
- dp = opendir(work);
- #ifdef DEBUG
- { char save_end = pattern[pathead];
- pattern[pathead] = 0;
- if_debug2('e', "[e]file_enum:fname='%s', p='%s'\n",
- work, pattern);
- pattern[pathead] = save_end;
- }
- #endif /* DEBUG */
- if (!dp)
- /* Can't list this one */
- goto top;
- else
- { /* Advance to the next directory-delimiter */
- /* in pattern */
- char *p;
- dirstack *d;
- for (p = pattern + pathead + 1; ; p++)
- { if (*p == 0)
- { /* No more subdirectories to match */
- pathead = pfen->patlen;
- break;
- }
- else if (*p == '/')
- { pathead = p - pattern;
- break;
- }
- }
-
- /* Push a directory onto the enumeration stack. */
- d = gs_alloc_struct(pfen->memory, dirstack,
- &st_dirstack,
- "gp_enumerate_files(pushdir)");
- if ( d != 0 )
- {
- d->next = pfen->dstack;
- d->entry = pfen->dirp;
- pfen->dstack = d;
- }
- else
- DO_NOTHING; /* >>> e_VMerror!!! */
-
- if_debug1('e', "[e]file_enum:Dir pushed '%s'\n",
- work);
- worklen = len;
- pfen->dirp = dp;
- goto top;
- }
- }
-
- winner:
- /* We have a winner! */
- pfen->worklen = worklen;
- pfen->pathead = pathead;
- memcpy(ptr, work, len);
- return len;
- }
-
- /* Clean up the file enumeration. */
- void
- gp_enumerate_files_close(file_enum *pfen)
- { gs_memory_t *mem = pfen->memory;
-
- if_debug0('e', "[e]file_enum:Cleanup\n");
- while (popdir(pfen)) /* clear directory stack */
- DO_NOTHING;
- gs_free_object(mem, (byte *)pfen->work,
- "gp_enumerate_close(work)");
- gs_free_object(mem, (byte *)pfen->pattern,
- "gp_enumerate_files_close(pattern)");
- gs_free_object(mem, pfen, "gp_enumerate_files_close");
- }
-
- /* Set a file into binary or text mode. */
- int
- gp_setmode_binary(FILE * pfile, bool binary)
- {
- return 0; /* Fake out dos return status */
- }
-
- /***************************************************************************/
- /* Functions from ixemul.library source which aren't in Libnix */
- /***************************************************************************/
- #ifndef IXEMUL
-
- /***************************************************************************/
- /* modf.c */
- /***************************************************************************/
- #include <proto/mathieeedoubbas.h>
-
- /*
- * modf(value, iptr): return fractional part of value, and stores the
- * integral part into iptr (a pointer to double).
- */
-
- double
- modf (double value, double *iptr)
- {
- /* if value negative */
- if (IEEEDPTst (value) < 0)
- {
- /* in that case, the integer part is calculated by ceil() */
- *iptr = IEEEDPCeil (value);
- return IEEEDPSub (*iptr, value);
- }
- else
- {
-
- /* if positive, we go for the floor() */
- *iptr = IEEEDPFloor (value);
- return IEEEDPSub (value, *iptr);
- }
- }
- /***************************************************************************/
- /* frexp.c */
- /***************************************************************************/
- #if defined(LIBC_SCCS) && !defined(lint)
- static char sccsid[] = "@(#)frexp.c 5.2 (Berkeley) 3/9/86";
- #endif LIBC_SCCS and not lint
-
- #define KERNEL
- /*#include "ixemul.h"*/
-
- /*
- * the call
- * x = frexp(arg,&exp);
- * must return a double fp quantity x which is <1.0
- * and the corresponding binary exponent "exp".
- * such that
- * arg = x*2^exp
- * if the argument is 0.0, return 0.0 mantissa and 0 exponent.
- */
-
- double
- frexp(double x, int *i)
- {
- int neg;
- int j;
-
- j = 0;
- neg = 0;
-
- if (x < 0)
- {
- x = -x;
- neg = 1;
- }
-
- if (x >= 1.0)
- while(x >= 1.0)
- {
- j = j+1;
- x = x/2;
- }
- else if(x < 0.5 && x != 0.0)
- while(x < 0.5)
- {
- j = j-1;
- x = 2*x;
- }
-
- *i = j;
- if (neg) x = -x;
- return x;
- }
-
- /***************************************************************************/
- /* ldexp.c */
- /***************************************************************************/
- /*
- * ldexp returns the quanity "value" * 2 ^ "exp"
- *
- * For the mc68000 using IEEE format the double precision word format is:
- *
- * WORD N => SEEEEEEEEEEEMMMM
- * WORD N+1 => MMMMMMMMMMMMMMMM
- * WORD N+2 => MMMMMMMMMMMMMMMM
- * WORD N+3 => MMMMMMMMMMMMMMMM
- *
- * Where: S => Sign bit
- * E => Exponent
- * X => Ignored (set to 0)
- * M => Mantissa bit
- *
- * NOTE: Beware of 0.0; on some machines which use excess 128 notation for the
- * exponent, if the mantissa is zero the exponent is also.
- *
- */
-
- #define MANT_MASK 0x800FFFFF /* Mantissa extraction mask */
- #define ZPOS_MASK 0x3FF00000 /* Positive # mask for exp = 0 */
- #define ZNEG_MASK 0x3FF00000 /* Negative # mask for exp = 0 */
-
- #define EXP_MASK 0x7FF00000 /* Mask for exponent */
- #define EXP_SHIFTS 20 /* Shifts to get into LSB's */
- #define EXP_BIAS 1023 /* Exponent bias */
-
-
- union dtol
- {
- double dval;
- int ival[2];
- };
-
- double
- ldexp (value, exp)
- double value;
- int exp;
- {
- union dtol number;
- int *iptr, cexp;
-
- if (value == 0.0)
- return (0.0);
- else
- {
- number.dval = value;
- iptr = &number.ival[0];
- cexp = (((*iptr) & EXP_MASK) >> EXP_SHIFTS) - EXP_BIAS;
- *iptr &= ~EXP_MASK;
- exp += EXP_BIAS;
- *iptr |= ((exp + cexp) << EXP_SHIFTS) & EXP_MASK;
- return (number.dval);
- }
- }
- #endif
-